/*
 * BlackLightning.PluginLib.Modules.Packets.SpeechCommandPacket
 * Andy Tidball
 * 
 * Project: Black Lightning Plugin Library
 * Copyright: GNU General Public License
 */

using System;
using System.Text.RegularExpressions;

namespace BlackLightning.PluginLib.Modules.Packets {
    /// <summary>
    /// A packet that represents a speech command.
    /// </summary>
    [Serializable]
    public abstract class SpeechCommandPacket : BLPacket {
        // member data
        private string _Text;     // the text of the speech
        private string _Target;   // the name of the person being spoken to
        private string _Tone;     // the tone being spoken in
        private string _Style;    // the style of speech
        private string _Language; // the language being spoken
        private string _Throw;    // the object the speech is being "thrown" behind

        /// <summary>
        /// Creates a new SpeechCommandPacket.
        /// </summary>
        /// <param name="Source">The program that the packet came from.</param>
        /// <param name="Destination">The program that the packet will be delivered to.</param>
        /// <param name="Data">The data string the packet was parsed from.</param>
        /// <param name="Text">The text being spoken.</param>
        /// <param name="Target">The name of the person being spoken to.</param>
        /// <param name="Tone">The tone of the speech.</param>
        /// <param name="Style">The style of the speech.</param>
        /// <param name="Language">The language being spoken.</param>
        /// <param name="Throw">The object the speech is being "thrown" behind.</param>
        protected SpeechCommandPacket(Program Source, Program Destination, string Data, string Text, string Target, string Tone, string Style, string Language, string Throw)
            : base(Source, Destination, Data) {
            _Text     = Text;
            _Target   = Target;
            _Tone     = Tone;
            _Style    = Style;
            _Language = Language;
            _Throw    = Throw;
        }
        
        /// <summary>
        /// Copy constructor.
        /// </summary>
        /// <param name="P">The SpeechCommandPacket to create a copy of.</param>
        /// <param name="DeepCopyOrNextState">True to make a deep copy of the given packet, false to instead use the given packet as the new packet's previous state.</param>
        protected SpeechCommandPacket(SpeechCommandPacket P, bool DeepCopyOrNextState)
            : base(P, DeepCopyOrNextState) {
            _Text     = P._Text;
            _Target   = P._Target;
            _Tone     = P._Tone;
            _Style    = P._Style;
            _Language = P._Language;
            _Throw    = P._Throw;
        }

        /// <summary>
        /// Gets or sets the text being spoken.
        /// </summary>
        public string Text {
            get {
                return _Text;
            }
            set {
                _Text = value;
            }
        }

        /// <summary>
        /// Gets or sets the name of the person being spoken to, or null if nobody is being spoken to directly.
        /// </summary>
        public string Target {
            get {
                return _Target;
            }
            set {
                _Target = value;
            }
        }

        /// <summary>
        /// Gets or sets the tone of the speech, or null if no tone is specified.
        /// </summary>
        public string Tone {
            get {
                return _Tone;
            }
            set {
                _Tone = value;
            }
        }

        /// <summary>
        /// Gets or sets the style of the speech, or null if no style is specified.
        /// </summary>
        public string Style {
            get {
                return _Style;
            }
            set {
                _Style = value;
            }
        }

        /// <summary>
        /// Gets or sets the language being spoken, or null if no language is specified.
        /// </summary>
        public string Language {
            get {
                return _Language;
            }
            set {
                _Language = value;
            }
        }

        /// <summary>
        /// Gets or sets the object to throw the voice behind, or null if no object is specified.
        /// </summary>
        public string Throw {
            get {
                return _Throw;
            }
            set {
                _Throw = value;
            }
        }
    }

    /// <summary>
    /// A filter for CommandPackets.
    /// </summary>
    [Serializable]
    public class SpeechCommandPacketFilter : BLPacketFilter {
        // member data
        private string _TextString     = null; // the string to match against the text of the speech
        private Regex  _TextRegex      = null; // the regular expression to match against the text of the speech
        private string _TargetString   = null; // the string to match against the name of the person being spoken to
        private Regex  _TargetRegex    = null; // the regular expression to match against the name of the person being spoken to
        private string _ToneString     = null; // the string to match against the tone being spoken in
        private Regex  _ToneRegex      = null; // the regular expression to match against the tone being spoken in
        private string _StyleString    = null; // the string to match against the style of speech
        private Regex  _StyleRegex     = null; // the regular expression to match against the style of speech
        private string _LanguageString = null; // the string to match against the language being spoken
        private Regex  _LanguageRegex  = null; // the regular expression to match against the language being spoken
        private string _ThrowString    = null; // the string to match against the object the speech is being "thrown" behind
        private Regex  _ThrowRegex     = null; // the regular expression to match against the object the speech is being "thrown" behind

        /// <summary>
        /// Creates a new SpeechCommandPacketFilter.
        /// </summary>
        /// <param name="Text">The string to match against the text of the speech.</param>
        public SpeechCommandPacketFilter(string Text) {
            _TextString = Text;
        }

        /// <summary>
        /// Creates a new SpeechCommandPacketFilter.
        /// </summary>
        /// <param name="Text">The regular expression to match against the text of the speech.</param>
        public SpeechCommandPacketFilter(Regex Text) {
            _TextRegex = Text;
        }

        /// <summary>
        /// Creates a new CommandPacketFilter.
        /// </summary>
        /// <param name="Source">The source program to match against the packet's source.</param>
        /// <param name="Destination">The destination program to match against the packet's destination.</param>
        public SpeechCommandPacketFilter(Program Source, Program Destination)
            : base(Source, Destination) {
        }

        /// <summary>
        /// Creates a new CommandPacketFilter.
        /// </summary>
        /// <param name="Source">The source program to match against the packet's source.</param>
        /// <param name="Destination">The destination program to match against the packet's destination.</param>
        /// <param name="Text">The string to match against the text of the speech.</param>
        public SpeechCommandPacketFilter(Program Source, Program Destination, string Text)
            : base(Source, Destination) {
            _TextString = Text;
        }

        /// <summary>
        /// Creates a new CommandPacketFilter.
        /// </summary>
        /// <param name="Source">The source program to match against the packet's source.</param>
        /// <param name="Destination">The destination program to match against the packet's destination.</param>
        /// <param name="Text">The regular expression to match against the text of the speech.</param>
        public SpeechCommandPacketFilter(Program Source, Program Destination, Regex Text)
            : base(Source, Destination) {
            _TextRegex = Text;
        }

        /// <summary>
        /// Gets or sets the string to match against the text of the speech.
        /// </summary>
        public string TextString { 
            get { 
                return _TextString; 
            }
            set {
                _TextString = value;
            } 
        }
        
        /// <summary>
        /// Gets or sets the regular expression to match against the text of the speech.
        /// </summary>
        public Regex TextRegex { 
            get {
                return _TextRegex;
            } 
            set {
                _TextRegex = value;
            } 
        }
        
        /// <summary>
        /// Gets or sets the string to match against the name of the person being spoken to.
        /// </summary>
        public string TargetString { 
            get {
                return _TargetString;
            } 
            set {
                _TargetString = value;
            }
        }
        
        /// <summary>
        /// Gets or sets the regular expression to match against the name of the person being spoken to.
        /// </summary>
        public Regex TargetRegex {
            get {
                return _TargetRegex;
            }
            set {
                _TargetRegex = value;
            }
        }
        
        /// <summary>
        /// Gets or sets the string to match against the tone being spoken in.
        /// </summary>
        public string ToneString {
            get { 
                return _ToneString;
            }
            set {
                _ToneString = value;
            }
        }
        
        /// <summary>
        /// Gets or sets the regular expression to match against the tone being spoken in.
        /// </summary>
        public Regex ToneRegex {
            get {
                return _ToneRegex;
            }
            set {
                _ToneRegex = value;
            }
        }
        
        /// <summary>
        /// Gets or sets the string to match against the style of speech.
        /// </summary>
        public string StyleString {
            get {
                return _StyleString;
            }
            set {
                _StyleString = value;
            }
        }
        
        /// <summary>
        /// Gets or sets the regular expression to match against the style of speech.
        /// </summary>
        public Regex StyleRegex { 
            get {
                return _StyleRegex;
            }
            set {
                _StyleRegex = value;
            }
        }
        
        /// <summary>
        /// Gets or set the string to match against the language being spoken.
        /// </summary>
        public string LanguageString {
            get {
                return _LanguageString;
            }
            set {
                _LanguageString = value;
            }
        }

        /// <summary>
        /// Gets or sets the regular expression to match against the language being spoken.
        /// </summary>
        public Regex LanguageRegex {
            get {
                return _LanguageRegex;
            }
            set {
                _LanguageRegex = value;
            }
        }
        
        /// <summary>
        /// Gets or sets the string to match against the object the speech is being "thrown" behind.
        /// </summary>
        public string ThrowString {
            get {
                return _ThrowString;
            }
            set {
                _ThrowString = value;
            }
        }
        
        /// <summary>
        /// Gets or sets the regular expression to match against the object the speech is being "thrown" behind.
        /// </summary>
        public Regex ThrowRegex {
            get {
                return _ThrowRegex;
            }
            set {
                _ThrowRegex = value;
            }
        }

        /// <summary>
        /// Matches the packet's dynamic data against the filter.
        /// </summary>
        /// <param name="Packet">The packet to match against the filter.</param>
        /// <returns>True if the packet's dynamic data matches the current setup of the filter, false if it does not.</returns>
        public override bool DynamicMatch(BLPacket Packet) {
            // make sure this is a SpeechCommandPacket
            SpeechCommandPacket P = Packet as SpeechCommandPacket;
            if (P == null) {
                return false;
            }

            // match the text
            if (_TextString != null && _TextString != P.Text) {
                return false;
            }
            if (_TextRegex != null && !_TextRegex.IsMatch(P.Text.Replace(Environment.NewLine, "\n"))) {
                return false;
            }

            // match the target
            if (_TargetString != null && _TargetString != P.Target) {
                return false;
            }
            if (_TargetRegex != null && !_TargetRegex.IsMatch(P.Target.Replace(Environment.NewLine, "\n"))) {
                return false;
            }

            // match the tone
            if (_ToneString != null && _ToneString != P.Tone) {
                return false;
            }
            if (_ToneRegex != null && !_ToneRegex.IsMatch(P.Tone.Replace(Environment.NewLine, "\n"))) {
                return false;
            }

            // match the style
            if (_StyleString != null && _StyleString != P.Style) {
                return false;
            }
            if (_StyleRegex != null && !_StyleRegex.IsMatch(P.Style.Replace(Environment.NewLine, "\n"))) {
                return false;
            }

            // match the language
            if (_LanguageString != null && _LanguageString != P.Language) {
                return false;
            }
            if (_LanguageRegex != null && !_LanguageRegex.IsMatch(P.Language.Replace(Environment.NewLine, "\n"))) {
                return false;
            }

            // match the throw
            if (_ThrowString != null && _ThrowString != P.Throw) {
                return false;
            }
            if (_ThrowRegex != null && !_ThrowRegex.IsMatch(P.Throw.Replace(Environment.NewLine, "\n"))) {
                return false;
            }

            // everything passed, match the base packet data
            return base.DynamicMatch(P);
        }
    }
}
